package urjc.as.emergencies.resources;

import org.apache.log4j.Logger;
import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Variant;

import urjc.as.emergencies.client.CommToolkit;
import urjc.as.emergencies.data.Mission;

/**
 * Restlet para gestionar las peticiones al recurso mission.
 * 
 * @author Helanacb
 * @author ahiges
 * 
 */
public class MissionResource extends BaseResource {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(MissionResource.class);

	public MissionResource(Context context, Request request, Response response) {
		super(context, request, response);

		// Variantes de representación soportadas
		getVariants().add(new Variant(MediaType.TEXT_XML));
	}

	// Allows
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.restlet.resource.Resource#allowDelete()
	 */
	@Override
	public boolean allowDelete() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.restlet.resource.Resource#allowGet()
	 */
	@Override
	public boolean allowGet() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.restlet.resource.Resource#allowPost()
	 */
	@Override
	public boolean allowPost() {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.restlet.resource.Resource#allowPut()
	 */
	@Override
	public boolean allowPut() {
		return false;
	}

	public boolean allowPatch() {
		return true;
	}

	// Manejadores
	/**
	 * Maneja las peticiones PATCH para actualización. Pueden ser las siguientes
	 * <li>idAmbulancia --> Si ponemos la ambulancia asignada además se le
	 * avisará a la ambulancia <li>estado --> Dependerá del estado concreto
	 * 
	 * @throws ResourceException
	 */
	public void handlePatch() throws ResourceException {

		getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);

		// 1) Obtenemos el recurso misión
		Mission mission = (Mission) getStorage().getEntity(
				getRequest().getResourceRef().getBaseRef().toString());

		// 2) Procesamos el patch
		Form form = getRequest().getEntityAsForm();

		// 2.1 Es un patch para idAmbulancia
		String ambulance = form.getFirstValue(Mission.AMBULANCE);
		if (ambulance != null) {
			logger.debug("Actualización ambulancia (" + ambulance
					+ ") asignada siendo procesada");
			if (mission.getAmbulance() != null) {
				getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST,
						"Ya tiene ambulancia asignada");
			} else {
				Status status = patchAmbulanciaMission(ambulance,
						mission.getIdMision());
				getResponse().setStatus(status);
				if (status.equals(Status.SUCCESS_OK)) {
					logger.debug("Ambulancia (" + ambulance
							+ ") asignada correctamente");
					mission.setAmbulance(ambulance);
					mission.setEstado(Mission.ESPERANDO_AMBULANCIA);
				}
			}
			// Comprueba la respuesta para antes de modificar el estado interno

		}

		// 2.2 Es un patch para el estado de la misión

		String statusS = form.getValues(Mission.STATUS);
		if (statusS != null) {
			try {
				int status = Integer.parseInt(statusS);
				logger.debug("Solicitud actualización estado en "
						+ mission.getUri());
				if (validaEstado(mission.getEstado(), status)) {
					// Modificamos el estado de la misión
					logger.debug("Status modificado correctamente");
					getResponse().setStatus(Status.SUCCESS_OK);
					mission.setEstado(status);
					if ((status == Mission.CLOSE || status == Mission.ABORT)
							&& mission.getAmbulance() != null) {

						// Avisa a la ambulancia para liberarla
						Status status1 = patchAmbulanciaMission(
								mission.getAmbulance(), -1);
						getResponse().setStatus(status1);
						if (status1.equals(Status.SUCCESS_OK)) {
							logger.debug("Status modificado correctamente");
							mission.setAmbulance("");
						}
					}

				} else {
					logger.debug("El nuevo estado no es coherente");
					getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST,
							"El nuevo estado no es coherente");
				}
			} catch (Exception e) {
				getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
				return;
			}
		}

	}
	

	@Override
	public void removeRepresentations() throws ResourceException {
		Mission mission = (Mission) getStorage().getEntity(getRequest().getResourceRef()
			    .getBaseRef()
			    .toString());
		
		if(canDelete(mission)){	
			
			getStorage().delEntity(mission.getUri());
			getResponse().setStatus(Status.SUCCESS_NO_CONTENT);		
		}else{
			getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST, "La mision no esta cerrada, no se puede eliminar");
		}
	}

	/**
	 * Comprueba si puede o no borrarse la misión
	 * @return
	 */
	private boolean canDelete(Mission mission) {
		if (mission.getEstado()== Mission.ABORT || mission.getEstado()== Mission.CLOSE)
			return true;
		else 
			return false;
	}

	private Status patchAmbulanciaMission(String ambulance, int missionID) {
		// Genera la petición
		return CommToolkit.actualizaRepresentacion(ambulance, "misionId",
				missionID + "");
	}

	/**
	 * Este método valida el status. En el caso de que el status sea de un tipo
	 * no podrá ser de algunos otros.
	 * 
	 * @param status
	 * @return
	 * 
	 *         public static final int ESPERANDO_ASISTENCIA = 1;
	 * 
	 *         public static final int ESPERANDO_AMBULANCIA = 2;
	 * 
	 *         public static final int SIENDO_ATENDIDO = 3;
	 * 
	 *         public static final int CAMINO_HOSPITAL = 4;
	 * 
	 *         public static final int EN_HOSPITAL = 5;
	 * 
	 *         public static final int CLOSE = 6;
	 */
	private boolean validaEstado(int statusMission, int status) {
		switch (statusMission) {
		case Mission.ESPERANDO_ASISTENCIA:
			if (status == Mission.ABORT)
				return true;
			else
				return false;
		case Mission.ESPERANDO_AMBULANCIA:
			if (status == Mission.SIENDO_ATENDIDO || status == Mission.ABORT)
				return true;
			else
				return false;
		case Mission.SIENDO_ATENDIDO:
			if (status == Mission.CAMINO_HOSPITAL || status == Mission.ABORT)
				return true;
			else
				return false;
		case Mission.CAMINO_HOSPITAL:
			if (status == Mission.EN_HOSPITAL || status == Mission.ABORT)
				return true;
			else
				return false;
		case Mission.EN_HOSPITAL:
			if (status == Mission.CLOSE || status == Mission.ABORT)
				return true;
			else
				return false;
		default:
			return false;
		}
	}
}
